package com.lakeworks.service.impl;

import com.alibaba.fastjson.JSON;
import com.lakeworks.common.core.text.Convert;
import com.lakeworks.common.exception.response.ResponseException;
import com.lakeworks.domain.SysFrame;
import com.lakeworks.domain.vo.FrameCreate;
import com.lakeworks.mapper.SysFrameMapper;
import com.lakeworks.service.ISysFrameService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

import static com.lakeworks.common.enums.ResponseEnum.*;
import static java.lang.Double.valueOf;
import static java.lang.Math.pow;
import static java.lang.String.format;

/**
 * 格架信息Service业务层处理
 *
 * @author lake
 * @date 2023-02-08
 */
@Slf4j
@Service
public class SysFrameServiceImpl implements ISysFrameService {

    private final String FRAME = "frame";

    private final String ISATT = "isAtt";

    private final String NOATT = "noAtt";

    @Resource
    private SysFrameMapper sysFrameMapper;

    @Resource(name = "StringRedisTemplate")
    private RedisTemplate redisTemplate;

    /**
     * 分配格架
     *
     * @param isAtt 是否附件格架
     */
    @Override
    public String allocateFrame(boolean isAtt) {

        DefaultTypedTuple<String> framePop = (DefaultTypedTuple) (isAtt ?
                redisTemplate.opsForZSet().popMin(format("%s:%s",FRAME,ISATT))
                :
                redisTemplate.opsForZSet().popMin(format("%s:%s",FRAME,NOATT)));

        if (framePop == null)
            throw new ResponseException(NO_FRAME_ALLOCATE);

        log.info("分配[{}]搁架，搁架号：[{}]", isAtt ? "附件" : "衣物", framePop.getValue());
        return framePop.getValue();
    }

    /**
     * 释放格架
     *
     * @param isAtta  是否附件格架
     * @param frameNo 格架号
     */
    @Override
    public void releaseFrame(boolean isAtta, String frameNo) {
        log.info("释放[{}]搁架，搁架号：[{}]", isAtta ? "附件" : "衣物", frameNo);

        SysFrame sysFrame = selectByFrameNo(frameNo);
        if (sysFrame == null)
            throw new ResponseException(FRAME_INEXISTENCE);

        if (!redisTemplate.opsForZSet().addIfAbsent(format("%s:%s",FRAME,isAtta ? ISATT : NOATT), sysFrame.getNo(), getScore(sysFrame.getNo())))
            throw new ResponseException(format("格架号[%s]释放失败",frameNo));
    }

    /**
     * 格架初始化
     */
    @Override
    public void initFrame() {
        log.info("frameNo redis init........");

        sysFrameMapper.selectUnusedFrameList()
                .forEach(sysFrame -> redisTemplate.opsForZSet()
                        .addIfAbsent(format("%s:%s",FRAME,sysFrame.getIsAttachment() ? ISATT : NOATT), sysFrame.getNo(), getScore(sysFrame.getNo()))
                );
    }

    @Override
    public void batchRelease(boolean isAtt, List<String> frameNos) {
        frameNos.forEach(frameNo -> redisTemplate.opsForZSet()
                .addIfAbsent(format("%s:%s",FRAME,isAtt ? ISATT : NOATT), frameNo, getScore(frameNo)));
    }

    /**
     * 获取搁架号对应 score
     */
    private Double getScore(String frameNo) {
        String postfix = frameNo.substring(1);
        try {
            return  ((int) frameNo.charAt(0) - 65) + valueOf(postfix) / (pow(10,postfix.length()));
        } catch (NumberFormatException e) {
            log.error("搁架号 -> score 转换失败",e);
            throw new RuntimeException("搁架号有误，获取score失败");
        }
    }

    @Override
    public void batchCreate(FrameCreate frameCreate) {

        for (Integer i = frameCreate.getStartNum(); i < frameCreate.getNum() + frameCreate.getStartNum(); i++) {
            SysFrame sysFrame = new SysFrame()
                    .setType("GRID")
                    .setIsAttachment(frameCreate.isAtt())
                    .setNo(frameCreate.getPrefix() + i)
                    .setCreateBy("恩情")
                    .setModifyBy("恩情");

            System.err.println(JSON.toJSONString(sysFrame));
//            insertSysFrame(sysFrame);
        }

    }

    /**
     * 查询格架信息
     *
     * @param id 格架信息主键
     * @return 格架信息
     */
    @Override
    public SysFrame selectSysFrameById(Long id) {
        return sysFrameMapper.selectSysFrameById(id);
    }

    @Override
    public SysFrame selectByFrameNo(String frameNo) {
        return sysFrameMapper.queryByFrameNo(frameNo);
    }

    /**
     * 查询格架信息列表
     *
     * @param sysFrame 格架信息
     * @return 格架信息
     */
    @Override
    public List<SysFrame> selectSysFrameList(SysFrame sysFrame) {
        return sysFrameMapper.selectSysFrameList(sysFrame);
    }

    /**
     * 新增格架信息
     *
     * @param sysFrame 格架信息
     * @return 结果
     */
    @Override
    public int insertSysFrame(SysFrame sysFrame) {
        return sysFrameMapper.insertSysFrame(sysFrame);
    }

    /**
     * 修改格架信息
     *
     * @param sysFrame 格架信息
     * @return 结果
     */
    @Override
    public int updateSysFrame(SysFrame sysFrame) {
        return sysFrameMapper.updateSysFrame(sysFrame);
    }

    /**
     * 批量删除格架信息
     *
     * @param ids 需要删除的格架信息主键
     * @return 结果
     */
    @Override
    public int deleteSysFrameByIds(String ids) {
        return sysFrameMapper.deleteSysFrameByIds(Convert.toStrArray(ids));
    }

    /**
     * 删除格架信息信息
     *
     * @param id 格架信息主键
     * @return 结果
     */
    @Override
    public int deleteSysFrameById(Long id) {
        return sysFrameMapper.deleteSysFrameById(id);
    }
}
